<template>
  <el-dialog
    title="批量操作"
    v-model="dialogVisible"
    width="65%"
  >
    <div class="batch-operations">
      <el-alert
        type="info"
        show-icon
        :closable="false"
      >
        <template #title>
          批量操作可能会对系统产生较大影响，请谨慎操作
        </template>
        <p>已选择 {{ selectedServices.length }} 个服务</p>
      </el-alert>
      
      <div class="service-selector">
        <div class="selector-header">
          <h3>选择服务</h3>
          <div class="selector-actions">
            <el-button size="small" @click="selectAll">全选</el-button>
            <el-button size="small" @click="selectNone">清空</el-button>
            <el-button size="small" @click="invertSelection">反选</el-button>
          </div>
        </div>
        
        <el-checkbox-group v-model="selectedServiceIds">
          <div class="services-list">
            <el-checkbox 
              v-for="service in services" 
              :key="service.id" 
              :label="service.id"
              border
            >
              <div class="service-item">
                <span class="service-name">{{ service.name }}</span>
                <el-tag size="small" :type="service.status === 'running' ? 'success' : 'danger'">
                  {{ service.status === 'running' ? '运行中' : '已停止' }}
                </el-tag>
              </div>
            </el-checkbox>
          </div>
        </el-checkbox-group>
      </div>
      
      <div class="operation-selector">
        <h3>选择操作</h3>
        <el-radio-group v-model="selectedOperation">
          <el-radio label="start">批量启动</el-radio>
          <el-radio label="stop">批量停止</el-radio>
          <el-radio label="restart">批量重启</el-radio>
          <el-radio label="refresh">刷新状态</el-radio>
        </el-radio-group>
      </div>
      
      <div class="operation-options">
        <h3>操作选项</h3>
        <el-form :model="options" label-width="120px">
          <el-form-item label="操作间隔" v-if="selectedOperation !== 'refresh'">
            <el-input-number 
              v-model="options.interval" 
              :min="0" 
              :max="10" 
              :step="0.5"
              :precision="1"
            /> 秒
            <div class="option-help">每个服务操作之间的时间间隔</div>
          </el-form-item>
          <el-form-item label="操作顺序">
            <el-radio-group v-model="options.order">
              <el-radio label="sequential">顺序执行</el-radio>
              <el-radio label="parallel">并行执行</el-radio>
            </el-radio-group>
            <div class="option-help">顺序执行：一个接一个地执行操作，等待前一个操作完成后再进行下一个</div>
            <div class="option-help">并行执行：同时对所有服务执行操作</div>
          </el-form-item>
          <el-form-item label="失败处理">
            <el-radio-group v-model="options.errorHandling">
              <el-radio label="continue">继续执行</el-radio>
              <el-radio label="stop">停止执行</el-radio>
            </el-radio-group>
            <div class="option-help">继续执行：即使某个服务操作失败，也继续执行其他服务的操作</div>
            <div class="option-help">停止执行：当某个服务操作失败时，立即停止整个批量操作</div>
          </el-form-item>
        </el-form>
      </div>
    </div>
    
    <div class="execution-progress" v-if="isExecuting">
      <h3>执行进度</h3>
      <el-progress 
        :percentage="executionProgress" 
        :status="executionStatus === 'error' ? 'exception' : executionStatus" 
        :striped="true"
        :striped-flow="true"
      />
      <div class="progress-details">
        <p>已完成: {{ completedCount }}/{{ selectedServices.length }}</p>
        <p v-if="executionStatus === 'error'">错误数: {{ errorCount }}</p>
      </div>
      <div class="progress-log">
        <div v-for="(log, index) in executionLogs" :key="index" class="log-entry">
          <el-tag size="small" :type="log.status === 'success' ? 'success' : 'danger'">
            {{ log.status === 'success' ? '成功' : '失败' }}
          </el-tag>
          <span class="log-service">{{ log.serviceName }}:</span>
          <span class="log-message">{{ log.message }}</span>
        </div>
      </div>
    </div>
    
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false" :disabled="isExecuting">取消</el-button>
        <el-button type="primary" @click="executeOperation" :loading="isExecuting" :disabled="!canExecute">
          {{ isExecuting ? '执行中...' : '执行操作' }}
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { useServiceStore, type Service } from '../stores/services'

interface ExecutionLog {
  serviceName: string
  message: string
  status: 'success' | 'error'
}

const props = defineProps<{
  visible: boolean
}>()

const emit = defineEmits(['update:visible', 'execution-complete'])

const serviceStore = useServiceStore()

const dialogVisible = ref(props.visible)
const selectedServiceIds = ref<number[]>([])
const selectedOperation = ref('start')
const options = ref({
  interval: 1.0,
  order: 'sequential',
  errorHandling: 'continue'
})

// 执行状态
const isExecuting = ref(false)
const executionProgress = ref(0)
const executionStatus = ref<'success' | 'exception' | 'error'>('success')
const completedCount = ref(0)
const errorCount = ref(0)
const executionLogs = ref<ExecutionLog[]>([])

watch(() => props.visible, (newValue) => {
  dialogVisible.value = newValue
  if (newValue) {
    // 对话框打开时重置选择状态
    selectedServiceIds.value = []
    resetExecutionState()
  }
})

watch(() => dialogVisible.value, (newValue) => {
  emit('update:visible', newValue)
})

const services = computed(() => {
  return serviceStore.services
})

const selectedServices = computed(() => {
  return services.value.filter(service => selectedServiceIds.value.includes(service.id))
})

const canExecute = computed(() => {
  return selectedServiceIds.value.length > 0 && !isExecuting.value
})

const selectAll = () => {
  selectedServiceIds.value = services.value.map(service => service.id)
}

const selectNone = () => {
  selectedServiceIds.value = []
}

const invertSelection = () => {
  const allIds = services.value.map(service => service.id)
  selectedServiceIds.value = allIds.filter(id => !selectedServiceIds.value.includes(id))
}

const resetExecutionState = () => {
  isExecuting.value = false
  executionProgress.value = 0
  executionStatus.value = 'success'
  completedCount.value = 0
  errorCount.value = 0
  executionLogs.value = []
}

const executeOperation = async () => {
  if (!selectedServices.value.length) {
    ElMessage.warning('请至少选择一个服务')
    return
  }
  
  resetExecutionState()
  isExecuting.value = true
  
  try {
    if (options.value.order === 'sequential') {
      await executeSequentially()
    } else {
      await executeInParallel()
    }
    
    ElMessage.success('批量操作执行完成')
    emit('execution-complete')
  } catch (error) {
    console.error('批量操作执行失败', error)
    ElMessage.error('批量操作执行失败')
  } finally {
    isExecuting.value = false
  }
}

const executeSequentially = async () => {
  const total = selectedServices.value.length
  let successful = 0
  let failed = 0
  
  for (let i = 0; i < selectedServices.value.length; i++) {
    const service = selectedServices.value[i]
    
    try {
      let success = false
      
      switch (selectedOperation.value) {
        case 'start':
          success = await serviceStore.startService(service.id)
          break
        case 'stop':
          success = await serviceStore.stopService(service.id)
          break
        case 'restart':
          success = await serviceStore.restartService(service.id)
          break
        case 'refresh':
          success = await serviceStore.checkServiceStatus(service.id)
          break
      }
      
      if (success) {
        successful++
        executionLogs.value.push({
          serviceName: service.name,
          message: `${getOperationName(selectedOperation.value)}成功`,
          status: 'success'
        })
      } else {
        failed++
        executionLogs.value.push({
          serviceName: service.name,
          message: `${getOperationName(selectedOperation.value)}失败`,
          status: 'error'
        })
        
        if (options.value.errorHandling === 'stop') {
          break
        }
      }
    } catch (error) {
      failed++
      executionLogs.value.push({
        serviceName: service.name,
        message: `执行出错: ${error}`,
        status: 'error'
      })
      
      if (options.value.errorHandling === 'stop') {
        break
      }
    }
    
    completedCount.value = successful + failed
    errorCount.value = failed
    executionProgress.value = Math.round((completedCount.value / total) * 100)
    
    if (failed > 0) {
      executionStatus.value = 'error'
    }
    
    // 添加操作间隔
    if (i < selectedServices.value.length - 1 && options.value.interval > 0) {
      await new Promise(resolve => setTimeout(resolve, options.value.interval * 1000))
    }
  }
}

const executeInParallel = async () => {
  const total = selectedServices.value.length
  const promises = selectedServices.value.map(async (service, index) => {
    try {
      let success = false
      
      switch (selectedOperation.value) {
        case 'start':
          success = await serviceStore.startService(service.id)
          break
        case 'stop':
          success = await serviceStore.stopService(service.id)
          break
        case 'restart':
          success = await serviceStore.restartService(service.id)
          break
        case 'refresh':
          success = await serviceStore.checkServiceStatus(service.id)
          break
      }
      
      if (success) {
        executionLogs.value.push({
          serviceName: service.name,
          message: `${getOperationName(selectedOperation.value)}成功`,
          status: 'success'
        })
        return { service, success: true }
      } else {
        executionLogs.value.push({
          serviceName: service.name,
          message: `${getOperationName(selectedOperation.value)}失败`,
          status: 'error'
        })
        return { service, success: false }
      }
    } catch (error) {
      executionLogs.value.push({
        serviceName: service.name,
        message: `执行出错: ${error}`,
        status: 'error'
      })
      return { service, success: false, error }
    }
  })
  
  const results = await Promise.all(promises)
  
  const successful = results.filter(r => r.success).length
  const failed = results.filter(r => !r.success).length
  
  completedCount.value = successful + failed
  errorCount.value = failed
  executionProgress.value = 100
  
  if (failed > 0) {
    executionStatus.value = 'error'
  }
}

const getOperationName = (op: string) => {
  switch (op) {
    case 'start': return '启动'
    case 'stop': return '停止'
    case 'restart': return '重启'
    case 'refresh': return '刷新状态'
    default: return op
  }
}

defineExpose({
  dialogVisible
})
</script>

<style scoped>
.batch-operations {
  margin-bottom: 20px;
}

.service-selector {
  margin-top: 20px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 15px;
}

.selector-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}

.services-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  max-height: 200px;
  overflow-y: auto;
}

.service-item {
  display: flex;
  align-items: center;
  min-width: 150px;
}

.service-name {
  margin-right: 10px;
}

.operation-selector {
  margin-top: 20px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 15px;
}

.operation-options {
  margin-top: 20px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 15px;
}

.option-help {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
  margin-top: 5px;
}

.execution-progress {
  margin-top: 30px;
  padding: 15px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}

.progress-details {
  display: flex;
  justify-content: space-between;
  margin: 10px 0;
}

.progress-log {
  max-height: 150px;
  overflow-y: auto;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
  margin-top: 10px;
}

.log-entry {
  margin-bottom: 5px;
  font-size: 12px;
}

.log-service {
  font-weight: bold;
  margin: 0 5px;
}

h3 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #303133;
}
</style> 